/**
 * AnimationMonitor.java Created on : 11 juin 07
 */
package fr.limsi.seven;

import java.util.LinkedList;

/**
 * @author Camille
 */
public class AnimationMonitor {

	/**
	 * Animation monitor <i>Singleton</i>
	 */
	protected static AnimationMonitor singleton = null;

	/**
	 * The monitor animationsQueue {@link Thread} list
	 */
	protected LinkedList<Animation> animationsQueue;

	/**
	 * The current alive animation {@link Thread}
	 */
	protected Animation currentAnimation;

	/**
	 * Getter for the <i>Singleton</i>
	 * 
	 * @return the {@link AnimationMonitor} <i>Singleton</i>
	 */
	public static AnimationMonitor getInstance() {
		if (singleton == null) {
			singleton = new AnimationMonitor();
		}
		return singleton;
	}

	/**
	 * Default constructor
	 */
	private AnimationMonitor() {
		singleton = this;
		animationsQueue = new LinkedList<Animation>();
		currentAnimation = null;
	}

	/**
	 * Add an animation {@link Animation} in the queue
	 * 
	 * @param animation
	 *            the {@link Animation} to add
	 */
	public synchronized void queueAnimation(Animation animation) {

		// Avoid view to blink with too many color changes
		while (!animationsQueue.isEmpty() && (animation.getType() == Animation.COLOR_ANIM && animationsQueue.getLast().getType() == animation.getType())) {
			animationsQueue.removeLast();
		}

		animationsQueue.addLast(animation);

		notify();
	}

	/**
	 * Pops an animation from the queue and starts it
	 */
	public synchronized void playAnimation() {

		while (animationsQueue.isEmpty() || currentAnimation != null) {
			try {
				wait();
			}
			catch (InterruptedException e) {
				e.printStackTrace();
			}
		}

		currentAnimation = animationsQueue.pop();
		currentAnimation.start();
	}

	/**
	 * Clears the queue
	 */
	public synchronized void flushAnimations() {
		animationsQueue.clear();
		notify();
	}

	/**
	 * Notifies the monitor that an animation has terminated
	 * 
	 * @param animationThread
	 *            the animation {@link Thread} that has terminated
	 */
	public synchronized void endReachedBy(Thread animationThread) {
		if (currentAnimation.getThread() == animationThread) {
			currentAnimation = null;
		}

		notify();
	}

	/**
	 * Getter for the current animation
	 * 
	 * @return the current played {@link Animation}
	 */
	public synchronized Animation getCurrentAnimation() {
		return currentAnimation;
	}
}
